home *** CD-ROM | disk | FTP | other *** search
/ Freaks Macintosh Archive / Freaks Macintosh Archive.bin / Freaks Macintosh Archives / Mp3 / MPEGAudioPlayerSource.cpt / map / maplay.cc < prev    next >
Text File  |  1994-11-16  |  13KB  |  447 lines

  1. /*
  2.  *  @(#) maplay.cc 1.20, last edit: 6/22/94 12:32:55
  3.  *  @(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de)
  4.  *  @(#) Berlin University of Technology
  5.  *
  6.  *  Many thanks for ideas and implementations to:
  7.  *  -> Jim Boucher (jboucher@flash.bu.edu)
  8.  *     for his idea and first implementation of 8 kHz u-law output
  9.  *  -> Louis P. Kruger (lpkruger@phoenix.princeton.edu)
  10.  *     for his implementation of the LinuxObuffer class
  11.  *
  12.  *  This program is free software; you can redistribute it and/or modify
  13.  *  it under the terms of the GNU General Public License as published by
  14.  *  the Free Software Foundation; either version 2 of the License, or
  15.  *  (at your option) any later version.
  16.  *
  17.  *  This program is distributed in the hope that it will be useful,
  18.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.  *  GNU General Public License for more details.
  21.  *
  22.  *  You should have received a copy of the GNU General Public License
  23.  *  along with this program; if not, write to the Free Software
  24.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  25.  */
  26.  
  27. /*
  28.  *  Changes from version 1.1 to 1.2:
  29.  *    - minor changes to create a LinuxObuffer object
  30.  *    - minor changes for a u-law version, which creates 8 kHz u-law output
  31.  *      on an amd device or in stdout mode, if compiled with ULAW defined
  32.  *    - option -amd forces maplay to treat /dev/audio as an amd device
  33.  *      in the u-law version. This is helpful on some SPARC clones.
  34.  *    - iostreams manipulator calls like "cerr << setw (2) << ..." replaced by
  35.  *      "cerr.width (2); ..." due to problems with older GNU C++ releases.
  36.  */
  37.  
  38. #include <stdlib.h>
  39. #include <string.h>
  40. #include <math.h>
  41. #include <iostream.h>
  42. //#include <iomanip.h>
  43. #include "all.h"
  44. #include "crc.h"
  45. #include "header.h"
  46. #include "ibitstream.h"
  47. #include "obuffer.h"
  48. #include "subband.h"
  49. #include "subband_layer_1.h"
  50. #include "subband_layer_2.h"
  51. #include "synthesis_filter.h"
  52.  
  53.  
  54. // data extracted from commandline arguments:
  55. static bool verbose_mode = False, filter_check = False;
  56. static bool stdout_mode = False;
  57. static enum e_channels which_channels = bothC;
  58. static bool use_speaker = False, use_headphone = False, use_line_out = False;
  59. #ifdef ULAW
  60. static bool force_amd = False;
  61. #endif
  62. static bool use_own_scalefactor = False;
  63. static real scalefactor;
  64.  
  65. // data extracted from header of first frame:
  66. static uint32 layer;
  67. static e_mode mode;
  68. static e_sample_frequency sample_frequency;
  69.  
  70. // objects needed for playing a file:
  71. static Ibitstream *stream;
  72. static Header *header;
  73. static Crc16 *crc;
  74. static Subband *subbands[32];
  75. static SynthesisFilter *filter1 = NULL, *filter2 = NULL;
  76. static Obuffer *buffer = NULL;
  77.  
  78.  
  79. static void Exit (int returncode)
  80.   // delete some objects and exit
  81. {
  82.   delete buffer;    // delete on NULL-pointers are harmless
  83.   delete filter1;
  84.   delete filter2;
  85.   delete header;
  86.   delete stream;
  87.   exit (returncode);
  88. }
  89.  
  90.  
  91. main2 (int argc, char *argv[], short refNums[])
  92. {
  93.   int i;
  94.  
  95.   if (argc < 2 || !strncmp (argv[1], "-h", 2))
  96.   {
  97. usage:
  98.     cerr << "\nusage: " << argv[0]
  99.      << " [-v] [-s] [-l] [-r] "
  100.         "[-c] [-f ushort] filename\n"
  101.         "  filename   filename of a MPEG audio stream or - for stdin\n"
  102.         "  -v         verbose mode\n"
  103.         "  -s         write pcm samples to stdout\n"
  104.         "  -l         decode only the left channel\n"
  105.         "  -r         decode only the right channel\n"
  106. #ifdef ULAW
  107.         "  -amd       force maplay to treat /dev/audio as an amd device\n"
  108. #endif
  109.         "  -c         check for filter range violations\n"
  110.         "  -f ushort  use this scalefactor instead of the default value 32768\n\n"
  111.         "@(#) MPEG Audio Player maplay 1.2 "
  112. #ifdef ULAW
  113.         "(8 kHz u-law "
  114. #else
  115.         "("
  116. #endif
  117.         "Macintosh"
  118.         " version)\n"
  119.         "@(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de)\n"
  120.         "@(#) Berlin University of Technology\n"
  121.         "@(#) Created: 6/23/94 14:12:46\n"
  122.         "@(#) This program is free software. See the GNU General Public License\n"
  123.         "@(#) in the file COPYING for more details.\n\n";
  124.     exit (0);
  125.   }
  126.  
  127.   // parse arguments:
  128.   for (i = 1; i < argc; ++i)
  129.     if (argv[i][0] == '-' && argv[i][1])
  130.       switch ((int)argv[i][1])
  131.       {
  132.     case 'v':
  133.       verbose_mode = True;
  134.       break;
  135.     case 's':
  136.       stdout_mode = True;
  137.       break;
  138.     case 'l':
  139.       which_channels = leftC;
  140.       break;
  141.     case 'r':
  142.       which_channels = rightC;
  143.       break;
  144. #ifdef MAC
  145.     case 'm':
  146.       use_speaker = True;
  147.       break;
  148. #endif
  149.  
  150. #ifdef ULAW
  151.     case 'a':
  152.       force_amd = True;
  153.       break;
  154. #endif
  155.     case 'c':
  156.       filter_check = True;
  157.       break;
  158.     case 'f':
  159.       if (++i == argc)
  160.       {
  161.         cerr << "please specify a new scalefactor after the -f option!\n";
  162.         exit (1);
  163.       }
  164.       use_own_scalefactor = True;
  165.       sscanf (argv[i], "%f", &scalefactor);
  166.       break;
  167.     default:
  168.       goto usage;
  169.       }
  170.     else
  171.       goto usage;
  172.  
  173.   if (!(use_speaker || use_headphone || use_line_out))
  174.     use_speaker = True;
  175.  
  176.   stream = new Ibitstream (refNums[0]);        // read from file
  177.  
  178.   header = new Header;
  179.   if (!header->read_header (stream, &crc))
  180.   {
  181.     cerr << "no header found!\n";
  182.     Exit (1);
  183.   }
  184.  
  185.   // get info from header of first frame:
  186.   layer = header->layer ();
  187.   if ((mode = header->mode ()) == single_channel)
  188.     which_channels = leftC;
  189.   sample_frequency = header->sample_frequency ();
  190.  
  191.    return (which_channels == bothC) + 1;
  192. }
  193.  
  194. void play_file(short refNums[])
  195. {
  196.   int i;
  197.   bool read_ready = False, write_ready = False;
  198.  
  199.   // create filter(s):
  200. #ifdef ULAW
  201.   if (use_own_scalefactor)
  202.     filter1 = new SynthesisFilter (0, sample_frequency, scalefactor);
  203.   else
  204.     filter1 = new SynthesisFilter (0, sample_frequency);
  205.   if (mode != single_channel && which_channels == bothC)
  206.     if (use_own_scalefactor)
  207.       filter2 = new SynthesisFilter (1, sample_frequency, scalefactor);
  208.     else
  209.       filter2 = new SynthesisFilter (1, sample_frequency);
  210. #else
  211.   if (use_own_scalefactor)
  212.     filter1 = new SynthesisFilter (0, scalefactor);
  213.   else
  214.     filter1 = new SynthesisFilter (0);
  215.   if (mode != single_channel && which_channels == bothC)
  216.     if (use_own_scalefactor)
  217.       filter2 = new SynthesisFilter (1, scalefactor);
  218.     else
  219.       filter2 = new SynthesisFilter (1);
  220. #endif    // !ULAW
  221.  
  222.   // create buffer:
  223.   if (stdout_mode)
  224.     if (mode == single_channel || which_channels != bothC)
  225.       buffer = new FileObuffer (1);
  226.     else
  227.       buffer = new FileObuffer (2);
  228.   else
  229. #ifdef MAC
  230.   {
  231.     if (MacObuffer::class_suitable (mode == single_channel || which_channels != bothC) ? 1 : 2)
  232.       if (mode == single_channel || which_channels != bothC)
  233.         buffer = new MacObuffer (1, header);    // mono
  234.       else
  235.         buffer = new MacObuffer (2, header);    // stereo
  236.   }
  237. #else
  238.   {
  239.     cerr << "Sorry, I don't know your audio device.\n"
  240.         "Please use the stdout mode.\n";
  241.     Exit (0);
  242.   }
  243. #endif    // !MAC
  244.  
  245. #ifdef MAC
  246.   if (stdout_mode)
  247. #endif
  248.   if (verbose_mode)
  249.   {
  250.     // print informations about the stream
  251.     cerr << "File is a layer " << header->layer_string () << ' '
  252.      << header->mode_string () << " MPEG audio stream with";
  253.     if (!header->checksums ())
  254.       cerr << "out";
  255.     cerr << " checksums.\nThe sample frequency is "
  256.      << header->sample_frequency_string () << " at a bitrate of "
  257.      << header->bitrate_string () << ".\n"
  258.         "This stream is ";
  259.     if (header->original ())
  260.       cerr << "an original";
  261.     else
  262.       cerr << "a copy";
  263.     cerr << " and is ";
  264.     if (!header->copyright ())
  265.       cerr << "not ";
  266.     cerr << "copyright protected.\n";
  267.   }
  268.  
  269.   do
  270.   {
  271.     // is there a change in important parameters?
  272.     // (bitrate switching is allowed)
  273.     if (header->layer () != layer)
  274.     {
  275.       // layer switching is allowed
  276.       if (verbose_mode)
  277.     cerr << "switching to layer " << header->layer_string () << ".\n";
  278.       layer = header->layer ();
  279.     }
  280.     if ((mode == single_channel && header->mode () != single_channel) ||
  281.     (mode != single_channel && header->mode () == single_channel))
  282.     {
  283.       // switching from single channel to stereo or vice versa is not allowed
  284.       cerr << "illegal switch from single channel to stereo or vice versa!\n";
  285.       Exit (1);
  286.     }
  287.     if (header->sample_frequency () != sample_frequency)
  288.     {
  289.       // switching the sample frequency is not allowed
  290.       cerr << "sorry, can't switch the sample frequency in the middle of the stream!\n";
  291.       Exit (1);
  292.     }
  293.  
  294.     // create subband objects:
  295.     if (header->layer () == 1)
  296.     {
  297.       if (header->mode () == single_channel)
  298.     for (i = 0; i < header->number_of_subbands (); ++i)
  299.       subbands[i] = new SubbandLayer1 (i);
  300.       else if (header->mode () == joint_stereo)
  301.       {
  302.     for (i = 0; i < header->intensity_stereo_bound (); ++i)
  303.       subbands[i] = new SubbandLayer1Stereo (i);
  304.     for (; i < header->number_of_subbands (); ++i)
  305.       subbands[i] = new SubbandLayer1IntensityStereo (i);
  306.       }
  307.       else
  308.     for (i = 0; i < header->number_of_subbands (); ++i)
  309.       subbands[i] = new SubbandLayer1Stereo (i);
  310.     }
  311.     else if (header->layer () == 2)
  312.     {
  313.       if (header->mode () == single_channel)
  314.     for (i = 0; i < header->number_of_subbands (); ++i)
  315.       subbands[i] = new SubbandLayer2 (i);
  316.       else if (header->mode () == joint_stereo)
  317.       {
  318.     for (i = 0; i < header->intensity_stereo_bound (); ++i)
  319.       subbands[i] = new SubbandLayer2Stereo (i);
  320.     for (; i < header->number_of_subbands (); ++i)
  321.       subbands[i] = new SubbandLayer2IntensityStereo (i);
  322.       }
  323.       else
  324.     for (i = 0; i < header->number_of_subbands (); ++i)
  325.       subbands[i] = new SubbandLayer2Stereo (i);
  326.     }
  327.     else
  328.     {
  329.       cerr << "sorry, layer 3 not implemented!\n";
  330.       Exit (0);
  331.     }
  332.  
  333.     // start to read audio data:
  334.     for (i = 0; i < header->number_of_subbands (); ++i)
  335.       subbands[i]->read_allocation (stream, header, crc);
  336.  
  337.     if (header->layer () == 2)
  338.       for (i = 0; i < header->number_of_subbands (); ++i)
  339.     ((SubbandLayer2 *)subbands[i])->read_scalefactor_selection (stream, crc);
  340.  
  341.     if (!crc || header->checksum_ok ())
  342.     {
  343.       // no checksums or checksum ok, continue reading from stream:
  344.       for (i = 0; i < header->number_of_subbands (); ++i)
  345.     subbands[i]->read_scalefactor (stream, header);
  346.  
  347.       do
  348.       {
  349.     for (i = 0; i < header->number_of_subbands (); ++i)
  350.       read_ready = subbands[i]->read_sampledata (stream);
  351.  
  352.     do
  353.     {
  354.       for (i = 0; i < header->number_of_subbands (); ++i)
  355.         write_ready = subbands[i]->put_next_sample (which_channels, filter1, filter2);
  356.  
  357.       filter1->calculate_pcm_samples (buffer);
  358.       if (which_channels == bothC && header->mode () != single_channel)
  359.         filter2->calculate_pcm_samples (buffer);
  360.     }
  361.     while (!write_ready);
  362.       }
  363.       while (!read_ready);
  364.  
  365.       buffer->write_buffer (refNums[1]);        // write to stdout
  366.       if (buffer->abort()) break;
  367.     }
  368.     else
  369.       // Sh*t! Wrong crc checksum in frame!
  370.       cerr << "WARNING: frame contains wrong crc checksum! (throwing frame away)\n";
  371.  
  372.     for (i = 0; i < header->number_of_subbands (); ++i)
  373.       delete subbands[i];
  374.   }
  375.   while (header->read_header (stream, &crc));
  376.  
  377.   delete buffer;
  378.  
  379. #ifdef MAC
  380. }
  381.  
  382. short post_process(void)
  383. {
  384.   uint32 range_violations = filter1->violations ();
  385.   if (mode != single_channel && which_channels == bothC)
  386.    range_violations += filter2->violations ();
  387.  
  388.   if (!stdout_mode && verbose_mode)
  389.   {
  390.     // print informations about the stream
  391.     cerr << "File is a layer " << header->layer_string () << ' '
  392.      << header->mode_string () << " MPEG audio stream with";
  393.     if (!header->checksums ())
  394.       cerr << "out";
  395.     cerr << " checksums.\nThe sample frequency is "
  396.      << header->sample_frequency_string () << " at a bitrate of "
  397.      << header->bitrate_string () << ".\n"
  398.         "This stream is ";
  399.     if (header->original ())
  400.       cerr << "an original";
  401.     else
  402.       cerr << "a copy";
  403.     cerr << " and is ";
  404.     if (!header->copyright ())
  405.       cerr << "not ";
  406.     cerr << "copyright protected.\n";
  407.   }
  408. #endif
  409.  
  410.   if (filter_check)
  411.   {
  412.     // check whether (one of) the filter(s) produced values not in [-1.0, 1.0]:
  413.     if (range_violations)
  414.     {
  415.       cerr << range_violations << " range violations have occured!\n";
  416.       if (stdout_mode)
  417.     cerr << "If you notice these violations,\n";
  418.       else
  419.     cerr << "If you have noticed these violations,\n";
  420.       cerr << "please use the -f option with the value ";
  421.       if (mode != single_channel && which_channels == bothC &&
  422.       filter2->hardest_violation () > filter1->hardest_violation ())
  423.     cerr << filter2->recommended_scalefactor ();
  424.       else
  425.     cerr << filter1->recommended_scalefactor ();
  426.       cerr << "\nor a greater value up to 32768 and try again.\n";
  427.     }
  428.   }
  429.   if (verbose_mode)
  430.   {
  431.     // print playtime of stream:
  432.     real playtime = filter1->seconds_played (Header::frequency (sample_frequency));
  433.     uint32 minutes = (uint32)(playtime / 60.0);
  434.     uint32 seconds = (uint32)playtime - minutes * 60;
  435.     uint32 centiseconds = (uint32)((playtime - (real)(minutes * 60) - (real)seconds) * 100.0);
  436.     cerr << "end of stream, playtime: " << minutes << ':';
  437.     cerr.width (2);
  438.     cerr.fill ('0');
  439.     cerr << seconds << '.';
  440.     cerr.width (2);
  441.     cerr.fill ('0');
  442.     cerr << centiseconds << '\n';
  443.   }
  444.  
  445.   return mode;
  446. }
  447.